/*/////////////////////////////////////////////////////////////////////////////////
/// An
///    ___   ____ ___ _____ ___  ____
///   / _ \ / ___|_ _|_   _/ _ \|  _ \
///  | | | | |  _ | |  | || | | | |_) |
///  | |_| | |_| || |  | || |_| |  _ <
///   \___/ \____|___| |_| \___/|_| \_\
///                              File
///
/// Copyright (c) 2008-2009 Ismail TARIM <ismail@royalspor.com> and the Ogitor Team
//
//This program is free software; you can redistribute it and/or modify it under
//the terms of the GNU Lesser General Public License as published by the Free Software
//Foundation; either version 2 of the License, or (at your option) any later
//version.
//
//This program is distributed in the hope that it will be useful, but WITHOUT
//ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
//FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
//You should have received a copy of the GNU Lesser General Public License along with
//this program; if not, write to the Free Software Foundation, Inc., 59 Temple
//Place - Suite 330, Boston, MA 02111-1307, USA, or go to
//http://www.gnu.org/copyleft/lesser.txt.
////////////////////////////////////////////////////////////////////////////////*/

/*////////////////////////////////////////////////////////////////////////////////
//This Header is used to define any library wide structs and enums and defines
////////////////////////////////////////////////////////////////////////////////*/

#pragma once

#include "OgitorsExports.h"

namespace Ogitors
{

#define OTR(a) m_System->Translate(a)

    const char OGITOR_VERSION[] = "0.3.2";    
    
    /** Enum containing a unique ID for any editor class */
    enum EDITORTYPE 
    {
        ETYPE_BASE = 0,         /** Base editor type */
        ETYPE_SCENEMANAGER,     /** Scene manager editor type */
        ETYPE_VIEWPORT,         /** Viewport editor type */
        ETYPE_CUSTOM_MANAGER,   /** Custom scene manager editor type */
        ETYPE_NODE,             /** Node editor type */
        ETYPE_LIGHT,            /** Light editor type */
        ETYPE_CAMERA,           /** Camera editor type */
        ETYPE_ENTITY,           /** Entity editor type */
        ETYPE_PLANE,            /** Plane editor type */
        ETYPE_PARTICLE,         /** Particle editor type */
        ETYPE_BILLBOARDSET,     /** Billboard set editor type */
        ETYPE_MOVABLE,          /** Movable editor type */
        ETYPE_MULTISEL,         /** Multi-selection editor type */
        ETYPE_MATERIAL          /** Material editor type */
    };

    /** String'ified EDITORTYPE enumeration @see EDITORTYPE */
    const Ogre::String EDITORTYPENAMES[] = 
    {
        "ETYPE_BASE",           /** String'ification of EDITORTYPE::ETYPE_BASE */
        "ETYPE_SCENEMANAGER",   /** String'ification of EDITORTYPE::ETYPE_SCENEMANAGER */
        "ETYPE_VIEWPORT",       /** String'ification of EDITORTYPE::ETYPE_VIEWPORT */
        "ETYPE_CUSTOM_MANAGER", /** String'ification of EDITORTYPE::ETYPE_CUSTOM_MANAGER */
        "ETYPE_NODE",           /** String'ification of EDITORTYPE::ETYPE_NODE */
        "ETYPE_LIGHT",          /** String'ification of EDITORTYPE::ETYPE_LIGHT */
        "ETYPE_CAMERA",         /** String'ification of EDITORTYPE::ETYPE_CAMERA */
        "ETYPE_ENTITY",         /** String'ification of EDITORTYPE::ETYPE_ENTITY */
        "ETYPE_PLANE",          /** String'ification of EDITORTYPE::ETYPE_PLANE */
        "ETYPE_PARTICLE",       /** String'ification of EDITORTYPE::ETYPE_PARTICLE */    
        "ETYPE_BILLBOARDSET",   /** String'ification of EDITORTYPE::ETYPE_BILLBOARDSET */
        "ETYPE_MOVABLE",        /** String'ification of EDITORTYPE::ETYPE_MOVABLE */
        "ETYPE_MULTISEL",       /** String'ification of EDITORTYPE::ETYPE_MULTISEL */
        "ETYPE_MATERIAL"        /** String'ification of EDITORTYPE::ETYPE_MATERIAL */
    };
    /** Last unique ID for an editor */
    const unsigned int LAST_EDITOR = ETYPE_MATERIAL + 1;

    struct CUSTOMPROPERTY;
    typedef std::vector<CUSTOMPROPERTY*> CustomPropertyList;

	typedef std::vector<Ogre::UTFString> UTFStringVector;
    //! Custom property structure
    /*!  
        A structure that is used to store User Defined Properties of an Object
    */
    struct CUSTOMPROPERTY
    {
        unsigned int        ID;             /** ID of the property */
        unsigned int        PARENTID;       /** Parent property' ID */
	    unsigned int        type;           /** Type of  property @see CUSTOMPROPERTYTYPE */
	    double              lowerbound;     /** Minimum value for the property */
	    double              upperbound;     /** Maximum value for the property */
	    Ogre::String        name;           /** Property name */
	    Ogre::String        value;          /** Property value */
	    Ogre::StringVector  options;        /** Additional options for the property (droplist-based) */
	    Ogre::StringVector  restrictions;   /** Restrictions for property (i.e. non-group property cannot contain members) */
	    CustomPropertyList  subproperties;  /** Sub-properties list (if this property is of group type) */
    };

    /** Undo/redo types enumeration */
    enum OGITORUNDOTYPE
    {
        UNDO_CREATE = 0,    /** Undoing creation operation (object destruction) */
        UNDO_DELETE = 1,    /** Undoing destruction operation (object resurrection) */
        UNDO_PROPERTY = 2,  /** Undoing property change (into previous value) */
        UNDO_CUSTOM = 3     /** @deprecated */
    };

    struct OGITORUNDOSTRUCT;

    typedef std::vector<OGITORUNDOSTRUCT> UndoList;

    //! Undo/redo structure
    /*!  
        A structure that holds single undo/redo operation and sub-operations for the object
    */
    struct OGITORUNDOSTRUCT
    {
        OGITORUNDOTYPE          m_Operation;        /** Type of an undo/redo operation */
        Ogre::NameValuePairList m_ObjectProperties; /** Information about the object */
        UndoList                m_SubData;          /** Additional operation(s) performed on an object */
        CustomPropertyList      m_CustomProperties; /** Custom object properties */
    };

    //! Drag'n'drop structure
    /*!  
        A structure that is used to track object state after initiating dragging
    */
    struct DRAGDATA
    {
        CBaseEditor *Object;                /** Pointer to Dragged Object */
		Ogre::String ObjectType;            /** Type of an object being dragged */
        Ogre::NameValuePairList Parameters; /** Information about the object */
    };

	/*!  
        A structure that holds a single object template
    */
    struct OGITORTEMPLATESTRUCT
    {
        Ogre::String mName;
        bool         mProjectScope;
        OGITORUNDOSTRUCT mData;
    };

    typedef std::vector<OGITORTEMPLATESTRUCT> TemplateList;

    /// Object List Definition
    typedef OgitorExport std::vector<CBaseEditor*> ObjectVector;

    /// A Hashed by Name Storage Definition for All Editors
    typedef OgitorExport HashMap<Ogre::String,CBaseEditor*> NameObjectPairList;

    /** 
        Property type enumeration that is used to define possible function IDs, all function IDs, 
        by having corresponding function(s) in CBaseEditor class
    */
    enum PROPERTYBINDING 
    {
		 BIND_NONE = 0,         /** Not binded to any property */
		 BIND_MAIN,             /** Main trunk of property widget' structure */
         BIND_TYPE,             /** Binding to the object' type */
         BIND_NAME,             /** Binding to object' name */
		 BIND_POSITION,         /** Binding to object' position */
         BIND_SCALE,            /** Binding to object' scale vector */
         BIND_ORIENTATION,      /** Binding to object' orientation quaternion */
         BIND_AABB,             /** Binding to object' AABB */
	     BIND_DIRECTION,        /** Binding to object' direction */
         BIND_AUTOTRACKTARGET,  /** Binding to object' Tracking Target */
         BIND_SUBENTITIES,      /** Binding to object' sub-entities root property */
         BIND_CASTSHADOWS,      /** Binding to object' casting of shadows flag */
	     BIND_CUSTOMPROPERTY    /** Binding to object' custom property(ies) root property */
    };

    /** Maximum number of predefined bindings */
	const int MAXIMUM_BINDING = BIND_CUSTOMPROPERTY + 1;
    /** Defines the base ID where all editor object dependent extra functions start */
    const int CUSTOM_BINDING_START = MAXIMUM_BINDING;
    /** Defines the base ID where all custom properties start */
    const int CUSTOM_PROPERTY_BINDING = CUSTOM_BINDING_START + 1000;

    /** The Axis enumeration */
	enum AXISTYPE 
    {
        AXIS_X = 1,     /** X Axis */
        AXIS_Y = 2,     /** Y Axis */
        AXIS_XY = 3,    /** XY Axis */
        AXIS_Z = 4,     /** Z Axis */
        AXIS_XZ = 5,    /** XZ Axis */
        AXIS_YZ = 6,    /** YZ Axis */
        AXIS_ALL = 7    /** XYZ Axis */
    };
    /** Capabilities enumeration for editor class(es) */
	enum EDITFLAGS 
    {
        CAN_MOVE   = 1,             /** Determines if editor object can be moved */
        CAN_SCALE  = 2,             /** Determines if editor object can be scaled */
        CAN_ROTATE = 4,             /** Determines if editor object can be rotated */
        CAN_DELETE = 8,             /** Determines if editor object can be deleted */
        CAN_CLONE  = 16,            /** Determines if editor object can be cloned */
        CAN_FOCUS  = 32,            /** Determines if editor object can be focused to when user presses focus key */
        CAN_DRAG   = 64 ,           /** Determines if editor object can be dragged */
        CAN_DROP   = 128,           /** Determines if editor object can be dropped to */
        CAN_UNDO   = 256,           /** Determines if editor object can perform undo/redo operation(s) */
        CAN_USEMATERIAL = 512,      /** Determines if editor object can receive a material through drag'n'drop */
        CAN_ACCEPTCOPY = 1024,      /** Determines if editor object can be copied */
        CAN_ACCEPTPASTE = 2048      /** Determines if editor object is a paste target */
    };

    /** Possible types of editor tools enumeration */
	enum EDITORTOOLS 
    {
        TOOL_SELECT = 0,    /** Selection mode, allowing for selection of object(s) */
        TOOL_MOVE,          /** Displacement mode, allowing for moving object(s) */
        TOOL_ROTATE,        /** Rotation mode, allowing for changing object(s) orientation */
        TOOL_SCALE,         /** Scale mode, allowing for scaling of object(s) */
        TOOL_DEFORM,        /** Deformation mode, allowing for deformation of certain meshes (terrain) */
        TOOL_SPLAT,         /** Splatting mode, allowing for splatting of textures on certain meshes (terrain) */
        TOOL_PAINT,         /** Painting mode, allowing for painting on certain meshes (terrain) */
        TOOL_SMOOTH         /** Smoothement mode, allowing for decreasing of amplitude of the mesh */
    };
    
    /** Additinal editor tools capabilities enumeration */
    enum EDITORTOOLSEX 
    {
        TOOL_EX_NONE = 0,   /** Default inaction */
        TOOL_EX_CLONE       /** Allows for cloning of selected object(s) */
    };

    /** This is the Query Flag for Widgets (To make picking them easier) */
	const unsigned int QUERYFLAG_WIDGET = 1;
    /** This is the Query Flag for any other MovableObject */
    const unsigned int QUERYFLAG_MOVABLE = 2;

    /** Custom property types enumeration  */
	enum CUSTOMPROPERTYTYPE 
    {
        CPTYPE_BASE,        /** Default custom property type */
        CPTYPE_GROUP,       /** Group-based custom property type */
        CPTYPE_STRING,      /** String-based custom property type */
        CPTYPE_INTEGER,     /** Integer-based custom property type */
        CPTYPE_FLOAT,       /** Float-based custom property type */
        CPTYPE_BOOLEAN,     /** Boolean-based custom property type */
        CPTYPE_VECTOR2,     /** Ogre::Vector2 based custom property type */
        CPTYPE_VECTOR3,     /** Ogre::Vector3 based custom property type */
        CPTYPE_VECTOR4,     /** Ogre::Vector4 based custom property type */
        CPTYPE_QUATERNION   /** Ogre::Quaternion based custom property type */
    };

    /** Enumeration-to-string convertion array (@see CUSTOMPROPERTYTYPE) */
	static const Ogre::String CUSTOMPROPERTYTYPENAMES[] = 
    {
        "base",         /** Default custom property type string */
        "group",        /** Group-based custom property type string */
        "string",       /** String-based custom property type string */
        "integer",      /** Integer-based custom property type string */
        "float",        /** Float-based custom property type string */
        "boolean",      /** Boolean-based custom property type string */
        "vector2",      /** Ogre::Vector2 based custom property type string */
        "vector3",      /** Ogre::Vector3 based custom property type string */
        "vector4",      /** Ogre::Vector4 based custom property type string */
        "quaternion"    /** Ogre::Quaternion based custom property type string */
    };

    /** Index of last custom property (for addition of other custom properties) */
	const unsigned int CUSTOM_PROPERTY_TYPECOUNT = CPTYPE_QUATERNION + 1;
    /** Maximum type index of an object */
	const unsigned int OGITOR_MAX_OBJECT_TYPE = 128;

    /** Dialog result (return) enumeration */
	enum DIALOGRET 
    {
        DLGRET_YES = 0, /** Dialog "Yes" return type */
        DLGRET_NO,      /** Dialog "No" return type */
        DLGRET_CANCEL   /** Dialog "Cancel" return type */
    };

    /** Dialog type enumeration */
	enum DIALOGTYPE 
    {
        DLGTYPE_OK = 0,             /** "OK" message box dialog type */
        DLGTYPE_YESNO = 1,          /** "Yes/No" confirmation dialog type */
        DLGTYPE_YESNOCANCEL = 2     /** "Yes/No/Cancel" confirmation dialog type */
    };
    
    /** Mouse cursor type enumeration */
    enum OgitorsMouseCursorType
    {
        MOUSE_ARROW = 0,            /** Arrow mouse cursor type */
        MOUSE_CROSS = 1             /** Cross mouse cursor type */
    };

    /** Ogitor mouse button enumeration */
    enum OgitorsMouseButtons
    {
        OMB_LEFT = 1,       /** Left mouse button type */
        OMB_RIGHT = 2,      /** Right mouse button type */
        OMB_MIDDLE = 4      /** Middle mouse button type */
    };
    
    /** Ogitor special keys bindings structure */
    struct OgitorsSpecialKeys
    {
       unsigned int SPK_LEFT;                       /** Left key flag */
       unsigned int SPK_RIGHT;                      /** Right key flag */
       unsigned int SPK_FORWARD;                    /** Forward key flag */
       unsigned int SPK_BACKWARD;                   /** Backwards key flag */
       unsigned int SPK_UP;                         /** Up key flag */
       unsigned int SPK_DOWN;                       /** Down key flag */
       unsigned int SPK_OBJECT_CENTERED_MOVEMENT;   /** Center-on-object key flag */
       unsigned int SPK_SNAP_GROUND;                /** Do Snap Object to the Ground key flag */
       unsigned int SPK_FOCUS_OBJECT;               /** Gain focus on selected object key flag */
       unsigned int SPK_CLONE;                      /** Clone object key flag */
       unsigned int SPK_DELETE;                     /** Delete object key flag */

       unsigned int SPK_REVERSE_UPDATE;             /** Reverses the direction of the tool (deform/splat) */
       unsigned int SPK_SWITCH_AXIS;                /** Next axis selection key flag */
       unsigned int SPK_SNAP;                       /** Snap to grid key flag */
       unsigned int SPK_ADD_TO_SELECTION;           /** Add to selection key flag */
       unsigned int SPK_SUBTRACT_FROM_SELECTION;    /** Subtract from selection key flag */
       unsigned int SPK_ALWAYS_SELECT;              /** Always select key flag */
    };

    /** Project options structure */
    struct PROJECTOPTIONS
    {
      bool               IsNewProject;              /** Flag specifying if project is newly created */
      Ogre::String       CreatedIn;                 /** the base directory of the Project Directory */
      Ogre::String       ProjectDir;                /** Root directory in which project file(s) to reside (absolute) */
      Ogre::String       ProjectName;               /** Name of the project */
      Ogre::String       SceneManagerName;          /** Scene manager name */
      Ogre::String       TerrainDirectory;          /** Terrain data directory name (relative)*/
      Ogre::String       HydraxDirectory;           /** Hydrax (water) data directory name (relative)*/
      Ogre::String       CaelumDirectory;           /** Caelum (sky) data directory name (relative) */
	  Ogre::String		 ParticleUniverseDirectory; /** ParticleUniverse data directory name (relative) */
      Ogre::String       PagedGeometryDirectory;    /** PagedGeometry data directory name (relative) */
      Ogre::String       SceneManagerConfigFile;    /** Scene manager configiration file name */   
      Ogre::StringVector ResourceDirectories;       /** A string list of resource directory(ies) */
      Ogre::Vector3      CameraPositions[11];       /** Camera positions array (scene can have multiple cameras) */
      Ogre::Quaternion   CameraOrientations[11];    /** Camera orientations array (scene can have multiple cameras) */
      int                CameraSaveCount;           /** Index of last created camera */
	  Ogre::ColourValue  SelectionBBColour;         /** Colour of the Selection Bounding Box */
	  Ogre::ColourValue  HighlightBBColour;         /** Colour of the Highlight Bounding Box */
	  Ogre::ColourValue  GridColour;                /** Colour of the Viewport Grid */
	  Ogre::Real         GridSpacing;               /** Spacing between Viewport Grid Cells */
	  Ogre::Real         SnapAngle;                 /** Angle to use as interval during snap to angle */
	};

    /** Ogitor Plugin Features enumeration */
    enum PluginFeatureTypes
    {
        PLUGIN_FEATURE_FACTORY = 1,      /** Plugin has registered editor factory(ies) */
        PLUGIN_FEATURE_SERIALIZER = 2,   /** Plugin has registered serializer(s) */
        PLUGIN_FEATURE_TOOLBAR = 4,      /** Plugin has registered toolbar(s) */
        PLUGIN_FEATURE_DOCKWINDOW = 8    /** Plugin has registered docking window(s) */
    };

    /** Structure to hold data about plugin entries */
    struct PLUGINENTRY
    {
        Ogre::String  mName;                        /** Name of the plugin */
        Ogre::String  mFileName;                    /** File name of the plugin */
        Ogre::DynLib *mLibrary;                     /** Pointer to plugin's library */
        Ogre::StringVector mEditorObjects;          /** List of Editor Objects this plugin registered */ 
        Ogre::StringVector mSerializers;            /** List of Serializers this plugin registered */ 
        std::vector<void*> mToolbars;               /** List of Toolbars this plugin registered */ 
        unsigned int  mFeatures;                    /** Bit field to store what his plugin adds to application*/  
    };

    typedef std::map<void *, PLUGINENTRY> PluginEntryMap;

    class CBaseEditorFactory;

    typedef std::map<Ogre::String, CBaseEditorFactory*> EditorObjectFactoryMap;

	/**
    * General inline function to validate attribute values read from an XML Element
    * @param val value to be verified
    * @param defaultvalue the default value to be set if val is null
    */
	inline const char * ValidAttr(const char * val,const char *defaultvalue = "")
	{
	    if(val)
	        return val;
	    else
	        return defaultvalue;
	}
};
